home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-wos-src / pasm / instructions.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  44KB  |  1,298 lines

  1. /* $VER: pasm instructions.c V1.2b (01.02.99)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2b  (01.02.99) phx
  16.  *        Fixed move_symbols() for move-deltas > alignment (e.g. .align 2)
  17.  * v1.2   (21.10.98) phx
  18.  *        @sdarx support for T_DD- and T_DS-type instructions.
  19.  *        Replaced obsolete R_PPC_TOC16 by real R_PPC_SDAREL16.
  20.  *        Fixed mfdcr and mtdcr.
  21.  * v1.1d  (27.09.98) phx
  22.  *        Optional PPC4xx instructions mfdcr and mtdcr.
  23.  * v1.1a  (20.06.98) phx
  24.  *        F_UPDATE. Check rA = rD for update instructions.
  25.  * v1.1   (19.06.98) phx
  26.  *        Multiple small data sections are supported. The new directive
  27.  *        .sdreg should be used to set the base register.
  28.  *        Fixed "Extra characters on line" error for "la rN,<symbol>".
  29.  *        Wrong error message (46) for "la rN,<absSymbol>". Changed to
  30.  *        error 32: reloc symbol required.
  31.  * v1.0   (21.05.98) phx
  32.  *        tlsync should have been tlbsync.
  33.  *        mtsrin is a supervisor instruction.
  34.  *        ME was not checked for rlwxxx.
  35.  *        mb/me in rldicxx is 6 bit, not 5.
  36.  * v0.9   (07.03.98) phx
  37.  *        Base relative access on external symbol generated wrong
  38.  *        relocation type.
  39.  *        R_ADDR16 relocations in code section had wrong offset.
  40.  *        R_REL14 branches will only get a 2-byte offset, if the output
  41.  *        format is EHF/ADOS and a relocation- or xref-entry is required.
  42.  * v0.8   (14.02.98) phx
  43.  *        Alignment list for each section. This fixes the problems
  44.  *        with optimizations.
  45.  * v0.7   (02.01.98) phx
  46.  *        Implemented optimization OPT_FAR_BRANCH.
  47.  * v0.6   (30.10.97) phx
  48.  *        No more warnings for val@l(rA), where val is > 0x7fff.
  49.  *        Warnings for optional, 64-bit and supervisor instructions
  50.  *        can be suppressed.
  51.  * v0.5   (03.10.97) phx
  52.  *        Auto-converting (rA) into 0(rA) had lead to conflicts with terms.
  53.  *        For example: (x+y)(rA)
  54.  * v0.4   (05.07.97) phx
  55.  *        AA bit in BC instructions is set to allow correct EHF reloction
  56.  *        (by using AmigaDOS HUNK_RELRELOC16. This should be no problem,
  57.  *        because absolute branches are not supported by EHF anyway.
  58.  *        Branch prediction with BCA didn't work correctly.
  59.  *        Relative branches into other sections are allowed, but the
  60.  *        user will be warned, because not all object formats / linkers
  61.  *        support it.
  62.  *        Omitting zero in load/store instructions is allowed, e.g.
  63.  *        "rD,(rA)" will be converted into "rD,0(rA)".
  64.  *        R_PPC_TOC16 support for T_DD- and T_DS-type instructions.
  65.  * v0.3   (05.04.97) phx
  66.  *        An external symbol@l/h/ha, used in d(Rn) addressing mode, got
  67.  *        R_PPC_ADDR16 relocation instead R_PPC_ADDR16_LO/HI/HA.
  68.  *        Little-endian support.
  69.  * v0.2   (25.03.97) phx
  70.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  71.  *        or ELF output format may be selected. ELF is default for all
  72.  *        currently supported platforms. PPCasm supports nine different
  73.  *        relocation types (there are much more...).
  74.  *        Compiles and works also under NetBSD/amiga (68k).
  75.  *        Changed function declaration to 'new style' in all sources
  76.  *        (to avoid problems with '...' for example).
  77.  *        @l/h/ha is allowed for all displacements.
  78.  * v0.1   (11.03.97) phx
  79.  *        First test version with all PowerPC instructions and most
  80.  *        important directives. Only raw, absolute output.
  81.  *        Although all 32- and 64-bit PowerPC instructions are imple-
  82.  *        mented, too few are really tested till now. I'm expecting many
  83.  *        bugs in this long list.
  84.  *        'la' is the only extended mnemonic, which was implemented as a
  85.  *        real instruction and not by a macro. It is possible to imple-
  86.  *        ment all extended mnemonics here, but it would be much work.
  87.  *        Maybe later, to improve speed. ;)
  88.  * v0.0   (21.02.97) phx
  89.  *        File created.
  90.  */
  91.  
  92.  
  93. #define INSTRUCTIONS_C
  94. #include "ppcasm.h"
  95.  
  96.  
  97. void instr(struct GlobalVars *,struct ParsedLine *);
  98. char *check_comma(char *);
  99. void pcadd(struct GlobalVars *,unsigned long);
  100. void store_byte(struct GlobalVars *,uint8);
  101. void store_half(struct GlobalVars *,uint16);
  102. void store_word(struct GlobalVars *,uint32);
  103. void store_float(struct GlobalVars *,double);
  104. void store_double(struct GlobalVars *,double);
  105. void store_space(struct GlobalVars *,unsigned long);
  106.  
  107. static void opt_far_branch(struct GlobalVars *,struct ParsedLine *,
  108.                            uint32 *,uint32 *,int32 *,char *);
  109. static void swapops(uint32 *,uint32 *);
  110. static int count_operands(struct GlobalVars *,char *);
  111. static bool chk_regindir(char *);
  112. static void move_symbols(struct GlobalVars *,uint32,int32);
  113. static void move_aligned_symbols_offset(struct GlobalVars *,
  114.                                         struct AlignPoint *,uint32,int32);
  115. static void move_aligned_symbols_all(struct GlobalVars *gv,
  116.                                      struct AlignPoint *ap,int32);
  117.  
  118.  
  119.  
  120. struct CPUInstr instructions[] = {
  121.   /* standard PowerPC instruction set */
  122.   { 0,"add",0,T_X,31,0,0,(0<<10)+(266<<1)+0 },
  123.   { 0,"add.",0,T_X,31,0,0,(0<<10)+(266<<1)+1 },
  124.   { 0,"addo",0,T_X,31,0,0,(1<<10)+(266<<1)+0 },
  125.   { 0,"addo.",0,T_X,31,0,0,(1<<10)+(266<<1)+1 },
  126.   { 0,"addc",0,T_X,31,0,0,(0<<10)+(10<<1)+0 },
  127.   { 0,"addc.",0,T_X,31,0,0,(0<<10)+(10<<1)+1 },
  128.   { 0,"addco",0,T_X,31,0,0,(1<<10)+(10<<1)+0 },
  129.   { 0,"addco.",0,T_X,31,0,0,(1<<10)+(10<<1)+1 },
  130.   { 0,"adde",0,T_X,31,0,0,(0<<10)+(138<<1)+0 },
  131.   { 0,"adde.",0,T_X,31,0,0,(0<<10)+(138<<1)+1 },
  132.   { 0,"addeo",0,T_X,31,0,0,(1<<10)+(138<<1)+0 },
  133.   { 0,"addeo.",0,T_X,31,0,0,(1<<10)+(138<<1)+1 },
  134.   { 0,"addi",F_SIGNED,T_DI,14,0,0,0 },
  135.   { 0,"addic",F_SIGNED,T_DI,12,0,0,0 },
  136.   { 0,"addic.",F_SIGNED,T_DI,13,0,0,0 },
  137.   { 0,"addis",F_SIGNED,T_DI,15,0,0,0 },
  138.   { 0,"addme",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+0 },
  139.   { 0,"addme.",F_SUPP_B,T_X,31,0,0,(0<<10)+(234<<1)+1 },
  140.   { 0,"addmeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+0 },
  141.   { 0,"addmeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(234<<1)+1 },
  142.   { 0,"addze",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+0 },
  143.   { 0,"addze.",F_SUPP_B,T_X,31,0,0,(0<<10)+(202<<1)+1 },
  144.   { 0,"addzeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+0 },
  145.   { 0,"addzeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(202<<1)+1 },
  146.   { 0,"and",F_SWAP,T_X,31,0,0,(28<<1)+0 },
  147.   { 0,"and.",F_SWAP,T_X,31,0,0,(28<<1)+1 },
  148.   { 0,"andc",F_SWAP,T_X,31,0,0,(60<<1)+0 },
  149.   { 0,"andc.",F_SWAP,T_X,31,0,0,(60<<1)+1 },
  150.   { 0,"andi.",F_SWAP,T_DI,28,0,0,0 },
  151.   { 0,"andis.",F_SWAP,T_DI,29,0,0,0 },
  152.   { 0,"b",F_SIGNED,T_I,18,0,0,0 },
  153.   { 0,"bl",F_SIGNED,T_I,18,0,0,1 },
  154.   { 0,"ba",0,T_I,18,0,0,2 },
  155.   { 0,"bla",0,T_I,18,0,0,3 },
  156.   { 0,"bc",F_SIGNED,T_B,16,0,0,0 },
  157.   { 0,"bcl",F_SIGNED,T_B,16,0,0,1 },
  158.   { 0,"bca",0,T_B,16,0,0,2 },
  159.   { 0,"bcla",0,T_B,16,0,0,3 },
  160.   { 0,"bcctr",0,T_XLB,19,0,0,(528<<1)+0 },
  161.   { 0,"bcctrl",0,T_XLB,19,0,0,(528<<1)+1 },
  162.   { 0,"bclr",0,T_XLB,19,0,0,(16<<1)+0 },
  163.   { 0,"bclrl",0,T_XLB,19,0,0,(16<<1)+1 },
  164.   { 0,"cmp",0,T_CMP,31,0,0,(0<<1) },
  165.   { 0,"cmpl",0,T_CMP,31,0,0,(32<<1) },
  166.   { 0,"cmpi",F_SIGNED|F_SUPP_B,T_CMP,11,0,0,0 },
  167.   { 0,"cmpli",F_SUPP_B,T_CMP,10,0,0,0 },
  168.   { 0,"cntlzd",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+0 },
  169.   { 0,"cntlzd.",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(58<<1)+1 },
  170.   { 0,"cntlzw",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+0 },
  171.   { 0,"cntlzw.",F_SWAP|F_SUPP_B,T_X,31,0,0,(26<<1)+1 },
  172.   { 0,"crand",0,T_X,19,0,0,(257<<1) },
  173.   { 0,"crandc",0,T_X,19,0,0,(129<<1) },
  174.   { 0,"creqv",0,T_X,19,0,0,(289<<1) },
  175.   { 0,"crnand",0,T_X,19,0,0,(225<<1) },
  176.   { 0,"crnor",0,T_X,19,0,0,(33<<1) },
  177.   { 0,"cror",0,T_X,19,0,0,(449<<1) },
  178.   { 0,"crorc",0,T_X,19,0,0,(417<<1) },
  179.   { 0,"crxor",0,T_X,19,0,0,(193<<1) },
  180.   { 0,"dcbf",F_SUPP_D,T_X,31,0,0,(86<<1) },
  181.   { 0,"dcbi",F_SUPP_D|F_SUPER,T_X,31,0,0,(470<<1) },
  182.   { 0,"dcbst",F_SUPP_D,T_X,31,0,0,(54<<1) },
  183.   { 0,"dcbt",F_SUPP_D,T_X,31,0,0,(278<<1) },
  184.   { 0,"dcbtst",F_SUPP_D,T_X,31,0,0,(246<<1) },
  185.   { 0,"dcbz",F_SUPP_D,T_X,31,0,0,(1014<<1) },
  186.   { 0,"divd",F_64BIT,T_X,31,0,0,(0<<10)+(489<<1)+0 },
  187.   { 0,"divd.",F_64BIT,T_X,31,0,0,(0<<10)+(489<<1)+1 },
  188.   { 0,"divdo",F_64BIT,T_X,31,0,0,(1<<10)+(489<<1)+0 },
  189.   { 0,"divdo.",F_64BIT,T_X,31,0,0,(1<<10)+(489<<1)+1 },
  190.   { 0,"divdu",F_64BIT,T_X,31,0,0,(0<<10)+(457<<1)+0 },
  191.   { 0,"divdu.",F_64BIT,T_X,31,0,0,(0<<10)+(457<<1)+1 },
  192.   { 0,"divduo",F_64BIT,T_X,31,0,0,(1<<10)+(457<<1)+0 },
  193.   { 0,"divduo.",F_64BIT,T_X,31,0,0,(1<<10)+(457<<1)+1 },
  194.   { 0,"divw",0,T_X,31,0,0,(0<<10)+(491<<1)+0 },
  195.   { 0,"divw.",0,T_X,31,0,0,(0<<10)+(491<<1)+1 },
  196.   { 0,"divwo",0,T_X,31,0,0,(1<<10)+(491<<1)+0 },
  197.   { 0,"divwo.",0,T_X,31,0,0,(1<<10)+(491<<1)+1 },
  198.   { 0,"divwu",0,T_X,31,0,0,(0<<10)+(459<<1)+0 },
  199.   { 0,"divwu.",0,T_X,31,0,0,(0<<10)+(459<<1)+1 },
  200.   { 0,"divwuo",0,T_X,31,0,0,(1<<10)+(459<<1)+0 },
  201.   { 0,"divwuo.",0,T_X,31,0,0,(1<<10)+(459<<1)+1 },
  202.   { 0,"eciwx",0,T_X,31,0,0,(310<<1) },
  203.   { 0,"ecowx",0,T_X,31,0,0,(438<<1) },
  204.   { 0,"eieio",F_SUPP_D|F_SUPP_A|F_SUPP_B,T_X,31,0,0,(854<<1) },
  205.   { 0,"eqv",F_SWAP,T_X,31,0,0,(284<<1)+0 },
  206.   { 0,"eqv.",F_SWAP,T_X,31,0,0,(284<<1)+0 },
  207.   { 0,"extsb",F_SWAP|F_SUPP_B,T_X,31,0,0,(954<<1)+0 },
  208.   { 0,"extsb.",F_SWAP|F_SUPP_B,T_X,31,0,0,(954<<1)+1 },
  209.   { 0,"extsh",F_SWAP|F_SUPP_B,T_X,31,0,0,(922<<1)+0 },
  210.   { 0,"extsh.",F_SWAP|F_SUPP_B,T_X,31,0,0,(922<<1)+1 },
  211.   { 0,"extsw",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(986<<1)+0 },
  212.   { 0,"extsw.",F_SWAP|F_SUPP_B|F_64BIT,T_X,31,0,0,(986<<1)+1 },
  213.   { 0,"fabs",F_SUPP_A,T_X,63,0,0,(264<<1)+0 },
  214.   { 0,"fabs.",F_SUPP_A,T_X,63,0,0,(264<<1)+1 },
  215.   { 0,"fadd",F_SUPP_C,T_A,63,0,0,(21<<1)+0 },
  216.   { 0,"fadd.",F_SUPP_C,T_A,63,0,0,(21<<1)+1 },
  217.   { 0,"fadds",F_SUPP_C,T_A,59,0,0,(21<<1)+0 },
  218.   { 0,"fadds.",F_SUPP_C,T_A,59,0,0,(21<<1)+1 },
  219.   { 0,"fcfid",F_SUPP_A|F_64BIT,T_X,63,0,0,(846<<1)+0 },
  220.   { 0,"fcfid.",F_SUPP_A|F_64BIT,T_X,63,0,0,(846<<1)+1 },
  221.   { 0,"fcmpo",F_CRF_D,T_X,63,0,0,(32<<1) },
  222.   { 0,"fcmpu",F_CRF_D,T_X,63,0,0,(0<<1) },
  223.   { 0,"fctid",F_SUPP_A|F_64BIT,T_X,63,0,0,(814<<1)+0 },
  224.   { 0,"fctid.",F_SUPP_A|F_64BIT,T_X,63,0,0,(814<<1)+1 },
  225.   { 0,"fctidz",F_SUPP_A|F_64BIT,T_X,63,0,0,(815<<1)+0 },
  226.   { 0,"fctidz.",F_SUPP_A|F_64BIT,T_X,63,0,0,(815<<1)+1 },
  227.   { 0,"fctiw",F_SUPP_A,T_X,63,0,0,(14<<1)+0 },
  228.   { 0,"fctiw.",F_SUPP_A,T_X,63,0,0,(14<<1)+1 },
  229.   { 0,"fctiwz",F_SUPP_A,T_X,63,0,0,(15<<1)+0 },
  230.   { 0,"fctiwz.",F_SUPP_A,T_X,63,0,0,(15<<1)+1 },
  231.   { 0,"fdiv",F_SUPP_C,T_A,63,0,0,(18<<1)+0 },
  232.   { 0,"fdiv.",F_SUPP_C,T_A,63,0,0,(18<<1)+1 },
  233.   { 0,"fdivs",F_SUPP_C,T_A,59,0,0,(18<<1)+0 },
  234.   { 0,"fdivs.",F_SUPP_C,T_A,59,0,0,(18<<1)+1 },
  235.   { 0,"fmadd",0,T_A,63,0,0,(29<<1)+0 },
  236.   { 0,"fmadd.",0,T_A,63,0,0,(29<<1)+1 },
  237.   { 0,"fmadds",0,T_A,59,0,0,(29<<1)+0 },
  238.   { 0,"fmadds.",0,T_A,59,0,0,(29<<1)+1 },
  239.   { 0,"fmr",F_SUPP_A,T_X,63,0,0,(72<<1)+0 },
  240.   { 0,"fmr.",F_SUPP_A,T_X,63,0,0,(72<<1)+1 },
  241.   { 0,"fmsub",0,T_A,63,0,0,(28<<1)+0 },
  242.   { 0,"fmsub.",0,T_A,63,0,0,(28<<1)+1 },
  243.   { 0,"fmsubs",0,T_A,59,0,0,(28<<1)+0 },
  244.   { 0,"fmsubs.",0,T_A,59,0,0,(28<<1)+1 },
  245.   { 0,"fmul",F_SUPP_B,T_A,63,0,0,(25<<1)+0 },
  246.   { 0,"fmul.",F_SUPP_B,T_A,63,0,0,(25<<1)+1 },
  247.   { 0,"fmuls",F_SUPP_B,T_A,59,0,0,(25<<1)+0 },
  248.   { 0,"fmuls.",F_SUPP_B,T_A,59,0,0,(25<<1)+1 },
  249.   { 0,"fnabs",F_SUPP_A,T_X,63,0,0,(136<<1)+0 },
  250.   { 0,"fnabs.",F_SUPP_A,T_X,63,0,0,(136<<1)+1 },
  251.   { 0,"fneg",F_SUPP_A,T_X,63,0,0,(40<<1)+0 },
  252.   { 0,"fneg.",F_SUPP_A,T_X,63,0,0,(40<<1)+1 },
  253.   { 0,"fnmadd",0,T_A,63,0,0,(31<<1)+0 },
  254.   { 0,"fnmadd.",0,T_A,63,0,0,(31<<1)+1 },
  255.   { 0,"fnmadds",0,T_A,59,0,0,(31<<1)+0 },
  256.   { 0,"fnmadds.",0,T_A,59,0,0,(31<<1)+1 },
  257.   { 0,"fnmsub",0,T_A,63,0,0,(30<<1)+0 },
  258.   { 0,"fnmsub.",0,T_A,63,0,0,(30<<1)+1 },
  259.   { 0,"fnmsubs",0,T_A,59,0,0,(30<<1)+0 },
  260.   { 0,"fnmsubs.",0,T_A,59,0,0,(30<<1)+1 },
  261.   { 0,"fres",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,59,0,0,(24<<1)+0 },
  262.   { 0,"fres.",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,59,0,0,(24<<1)+1 },
  263.   { 0,"frsp",F_SUPP_A,T_X,63,0,0,(12<<1)+0 },
  264.   { 0,"frsp.",F_SUPP_A,T_X,63,0,0,(12<<1)+1 },
  265.   { 0,"frsqrte",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,63,0,0,(26<<1)+0 },
  266.   { 0,"frsqrte.",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,63,0,0,(26<<1)+1 },
  267.   { 0,"fsel",F_OPTIONAL,T_A,63,0,0,(23<<1)+0 },
  268.   { 0,"fsel.",F_OPTIONAL,T_A,63,0,0,(23<<1)+1 },
  269.   { 0,"fsqrt",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,63,0,0,(22<<1)+0 },
  270.   { 0,"fsqrt.",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,63,0,0,(22<<1)+1 },
  271.   { 0,"fsqrts",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,59,0,0,(22<<1)+0 },
  272.   { 0,"fsqrts.",F_SUPP_A|F_SUPP_C|F_OPTIONAL,T_A,59,0,0,(22<<1)+1 },
  273.   { 0,"fsub",F_SUPP_C,T_A,63,0,0,(20<<1)+0 },
  274.   { 0,"fsub.",F_SUPP_C,T_A,63,0,0,(20<<1)+1 },
  275.   { 0,"fsubs",F_SUPP_C,T_A,59,0,0,(20<<1)+0 },
  276.   { 0,"fsubs.",F_SUPP_C,T_A,59,0,0,(20<<1)+1 },
  277.   { 0,"icbi",F_SUPP_D,T_X,31,0,0,(982<<1) },
  278.   { 0,"isync",F_SUPP_D|F_SUPP_A|F_SUPP_B,T_X,19,0,0,(150<<1) },
  279.   { 0,"lbz",0,T_DD,34,0,0,0 },
  280.   { 0,"lbzu",F_UPDATE,T_DD,35,0,0,0 },
  281.   { 0,"lbzux",F_UPDATE,T_X,31,0,0,(119<<1) },
  282.   { 0,"lbzx",0,T_X,31,0,0,(87<<1) },
  283.   { 0,"ld",F_64BIT,T_DS,58,0,0,0 },
  284.   { 0,"ldarx",F_64BIT,T_X,31,0,0,(84<<1) },
  285.   { 0,"ldu",F_64BIT|F_UPDATE,T_DS,58,0,0,1 },
  286.   { 0,"ldux",F_64BIT|F_UPDATE,T_X,31,0,0,(53<<1) },
  287.   { 0,"ldx",F_64BIT,T_X,31,0,0,(21<<1) },
  288.   { 0,"lfd",0,T_DD,50,0,0,0 },
  289.   { 0,"lfdu",0,T_DD,51,0,0,0 },
  290.   { 0,"lfdux",0,T_X,31,0,0,(631<<1) },
  291.   { 0,"lfdx",0,T_X,31,0,0,(599<<1) },
  292.   { 0,"lfs",0,T_DD,48,0,0,0 },
  293.   { 0,"lfsu",0,T_DD,49,0,0,0 },
  294.   { 0,"lfsux",0,T_X,31,0,0,(567<<1) },
  295.   { 0,"lfsx",0,T_X,31,0,0,(535<<1) },
  296.   { 0,"lha",0,T_DD,42,0,0,0 },
  297.   { 0,"lhau",F_UPDATE,T_DD,43,0,0,0 },
  298.   { 0,"lhaux",F_UPDATE,T_X,31,0,0,(375<<1) },
  299.   { 0,"lhax",0,T_X,31,0,0,(343<<1) },
  300.   { 0,"lhbrx",0,T_X,31,0,0,(790<<1) },
  301.   { 0,"lhz",0,T_DD,40,0,0,0 },
  302.   { 0,"lhzu",F_UPDATE,T_DD,41,0,0,0 },
  303.   { 0,"lhzux",F_UPDATE,T_X,31,0,0,(311<<1) },
  304.   { 0,"lhzx",0,T_X,31,0,0,(279<<1) },
  305.   { 0,"lmw",0,T_DD,46,0,0,0 },
  306.   { 0,"lswi",0,T_X,31,0,0,(597<<1) },
  307.   { 0,"lswx",0,T_X,31,0,0,(533<<1) },
  308.   { 0,"lwa",F_64BIT,T_DS,58,0,0,2 },
  309.   { 0,"lwarx",0,T_X,31,0,0,(20<<1) },
  310.   { 0,"lwaux",F_64BIT|F_UPDATE,T_X,31,0,0,(373<<1) },
  311.   { 0,"lwax",F_64BIT,T_X,31,0,0,(341<<1) },
  312.   { 0,"lwbrx",0,T_X,31,0,0,(534<<1) },
  313.   { 0,"lwz",0,T_DD,32,0,0,0 },
  314.   { 0,"lwzu",F_UPDATE,T_DD,33,0,0,0 },
  315.   { 0,"lwzux",F_UPDATE,T_X,31,0,0,(55<<1) },
  316.   { 0,"lwzx",0,T_X,31,0,0,(23<<1) },
  317.   { 0,"mcrf",F_CRF_D|F_CRF_S|F_SUPP_B,T_X,19,0,0,(0<<1) },
  318.   { 0,"mcrfs",F_CRF_D|F_CRF_S|F_SUPP_B,T_X,63,0,0,(64<<1) },
  319.   { 0,"mcrxr",F_CRF_D|F_SUPP_A|F_SUPP_B,T_X,31,0,0,(512<<1) },
  320.   { 0,"mfcr",F_SUPP_A|F_SUPP_B,T_X,31,0,0,(19<<1) },
  321.   { 0,"mffs",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(583<<1)+0 },
  322.   { 0,"mffs.",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(583<<1)+1 },
  323.   { 0,"mfmsr",F_SUPP_A|F_SUPP_B|F_SUPER,T_X,31,0,0,(83<<1) },
  324.   { 0,"mfdcr",F_OPTIONAL,T_XSPR,31,0,0,(323<<1) },  /* PPC4xx - jab */
  325.   { 0,"mfspr",0,T_XSPR,31,0,0,(339<<1) },
  326.   { 0,"mfsr",F_SUPP_B|F_SUPER,T_X,31,0,0,(595<<1) },
  327.   { 0,"mfsrin",F_SUPP_A|F_SUPER,T_X,31,0,0,(659<<1) },
  328.   { 0,"mftb",0,T_XSPR,31,0,0,(371<<1) },
  329.   { 0,"mtcrf",0,T_XCRM,31,0,0,(144<<1) },
  330.   { 0,"mtfsb0",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(70<<1)+0 },
  331.   { 0,"mtfsb0.",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(70<<1)+1 },
  332.   { 0,"mtfsb1",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(38<<1)+0 },
  333.   { 0,"mtfsb1.",F_SUPP_A|F_SUPP_B,T_X,63,0,0,(38<<1)+1 },
  334.   { 0,"mtfsf",0,T_XFL,63,0,0,(711<<1)+0 },
  335.   { 0,"mtfsf.",0,T_XFL,63,0,0,(711<<1)+1 },
  336.   { 0,"mtfsfi",0,T_IMM,63,0,0,(134<<1)+0 },
  337.   { 0,"mtfsfi.",0,T_IMM,63,0,0,(134<<1)+1 },
  338.   { 0,"mtmsr",F_SUPP_A|F_SUPP_B|F_SUPER,T_X,31,0,0,(146<<1) },
  339.   { 0,"mtdcr",F_SWAP|F_OPTIONAL,T_XSPR,31,0,0,(451<<1) },  /* PPC4xx - jab */
  340.   { 0,"mtspr",F_SWAP,T_XSPR,31,0,0,(467<<1) },
  341.   { 0,"mtsr",F_SWAP|F_SUPP_B|F_SUPER,T_X,31,0,0,(210<<1) },
  342.   { 0,"mtsrin",F_SUPP_A|F_SUPER,T_X,31,0,0,(242<<1) },
  343.   { 0,"mulhd",F_64BIT,T_X,31,0,0,(73<<1)+0 },
  344.   { 0,"mulhd.",F_64BIT,T_X,31,0,0,(73<<1)+1 },
  345.   { 0,"mulhdu",F_64BIT,T_X,31,0,0,(9<<1)+0 },
  346.   { 0,"mulhdu.",F_64BIT,T_X,31,0,0,(9<<1)+1 },
  347.   { 0,"mulhw",0,T_X,31,0,0,(75<<1)+0 },
  348.   { 0,"mulhw.",0,T_X,31,0,0,(75<<1)+1 },
  349.   { 0,"mulhwu",0,T_X,31,0,0,(11<<1)+0 },
  350.   { 0,"mulhwu.",0,T_X,31,0,0,(11<<1)+1 },
  351.   { 0,"mulld",F_64BIT,T_X,31,0,0,(0<<10)+(233<<1)+0 },
  352.   { 0,"mulld.",F_64BIT,T_X,31,0,0,(0<<10)+(233<<1)+1 },
  353.   { 0,"mulldo",F_64BIT,T_X,31,0,0,(1<<10)+(233<<1)+0 },
  354.   { 0,"mulldo.",F_64BIT,T_X,31,0,0,(1<<10)+(233<<1)+1 },
  355.   { 0,"mulli",F_SIGNED,T_DI,7,0,0,0 },
  356.   { 0,"mullw",0,T_X,31,0,0,(0<<10)+(235<<1)+0 },
  357.   { 0,"mullw.",0,T_X,31,0,0,(0<<10)+(235<<1)+1 },
  358.   { 0,"mullwo",0,T_X,31,0,0,(1<<10)+(235<<1)+0 },
  359.   { 0,"mullwo.",0,T_X,31,0,0,(1<<10)+(235<<1)+1 },
  360.   { 0,"nand",F_SWAP,T_X,31,0,0,(476<<1)+0 },
  361.   { 0,"nand.",F_SWAP,T_X,31,0,0,(476<<1)+1 },
  362.   { 0,"neg",F_SUPP_B,T_X,31,0,0,(0<<10)+(104<<1)+0 },
  363.   { 0,"neg.",F_SUPP_B,T_X,31,0,0,(0<<10)+(104<<1)+1 },
  364.   { 0,"nego",F_SUPP_B,T_X,31,0,0,(1<<10)+(104<<1)+0 },
  365.   { 0,"nego.",F_SUPP_B,T_X,31,0,0,(1<<10)+(104<<1)+1 },
  366.   { 0,"nor",F_SWAP,T_X,31,0,0,(124<<1)+0 },
  367.   { 0,"nor.",F_SWAP,T_X,31,0,0,(124<<1)+1 },
  368.   { 0,"or",F_SWAP,T_X,31,0,0,(444<<1)+0 },
  369.   { 0,"or.",F_SWAP,T_X,31,0,0,(444<<1)+1 },
  370.   { 0,"orc",F_SWAP,T_X,31,0,0,(412<<1)+0 },
  371.   { 0,"orc.",F_SWAP,T_X,31,0,0,(412<<1)+1 },
  372.   { 0,"ori",F_SWAP,T_DI,24,0,0,0 },
  373.   { 0,"oris",F_SWAP,T_DI,25,0,0,0 },
  374.   { 0,"rfi",F_SUPP_D|F_SUPP_A|F_SUPP_B|F_SUPER,T_X,19,0,0,(50<<1) },
  375.   { 0,"rldcl",F_SWAP|F_64BIT,T_A,30,0,0,(8<<1)+0 },
  376.   { 0,"rldcl.",F_SWAP|F_64BIT,T_A,30,0,0,(8<<1)+1 },
  377.   { 0,"rldcr",F_SWAP|F_64BIT,T_A,30,0,0,(9<<1)+0 },
  378.   { 0,"rldcr.",F_SWAP|F_64BIT,T_A,30,0,0,(9<<1)+1 },
  379.   { 0,"rldic",F_64BIT,T_MD,30,0,0,(2<<2)+0 },
  380.   { 0,"rldic.",F_64BIT,T_MD,30,0,0,(2<<2)+1 },
  381.   { 0,"rldicl",F_64BIT,T_MD,30,0,0,(0<<2)+0 },
  382.   { 0,"rldicl.",F_64BIT,T_MD,30,0,0,(0<<2)+1 },
  383.   { 0,"rldicr",F_64BIT,T_MD,30,0,0,(1<<2)+0 },
  384.   { 0,"rldicr.",F_64BIT,T_MD,30,0,0,(1<<2)+1 },
  385.   { 0,"rldimi",F_64BIT,T_MD,30,0,0,(3<<2)+0 },
  386.   { 0,"rldimi.",F_64BIT,T_MD,30,0,0,(3<<2)+1 },
  387.   { 0,"rlwimi",0,T_M,20,0,0,0 },
  388.   { 0,"rlwimi.",0,T_M,20,0,0,1 },
  389.   { 0,"rlwinm",0,T_M,21,0,0,0 },
  390.   { 0,"rlwinm.",0,T_M,21,0,0,1 },
  391.   { 0,"rlwnm",0,T_M,23,0,0,0 },
  392.   { 0,"rlwnm.",0,T_M,23,0,0,1 },
  393.   { 0,"sc",F_SUPP_D|F_SUPP_A|F_SUPP_B,T_X,17,0,0,2 },
  394.   { 0,"slbia",F_SUPP_D|F_SUPP_A|F_SUPP_B|F_SUPER|F_64BIT|F_OPTIONAL,
  395.     T_X,31,0,0,(498<<1) },
  396.   { 0,"slbie",F_SUPP_D|F_SUPP_A|F_SUPER|F_64BIT|F_OPTIONAL,
  397.     T_X,31,0,0,(434<<1) },
  398.   { 0,"sld",F_SWAP|F_64BIT,T_X,31,0,0,(27<<1)+0 },
  399.   { 0,"sld.",F_SWAP|F_64BIT,T_X,31,0,0,(27<<1)+1 },
  400.   { 0,"slw",F_SWAP,T_X,31,0,0,(24<<1)+0 },
  401.   { 0,"slw.",F_SWAP,T_X,31,0,0,(24<<1)+1 },
  402.   { 0,"srad",F_SWAP|F_64BIT,T_X,31,0,0,(794<<1)+0 },
  403.   { 0,"srad.",F_SWAP|F_64BIT,T_X,31,0,0,(794<<1)+1 },
  404.   { 0,"sradi",F_64BIT,T_XS,31,0,0,(413<<2)+0 },
  405.   { 0,"sradi.",F_64BIT,T_XS,31,0,0,(413<<2)+1 },
  406.   { 0,"sraw",F_SWAP,T_X,31,0,0,(792<<1)+0 },
  407.   { 0,"sraw.",F_SWAP,T_X,31,0,0,(792<<1)+1 },
  408.   { 0,"srawi",F_SWAP,T_X,31,0,0,(824<<1)+0 },
  409.   { 0,"srawi.",F_SWAP,T_X,31,0,0,(824<<1)+1 },
  410.   { 0,"srd",F_SWAP|F_64BIT,T_X,31,0,0,(539<<1)+0 },
  411.   { 0,"srd.",F_SWAP|F_64BIT,T_X,31,0,0,(539<<1)+1 },
  412.   { 0,"srw",F_SWAP,T_X,31,0,0,(536<<1)+0 },
  413.   { 0,"srw.",F_SWAP,T_X,31,0,0,(536<<1)+1 },
  414.   { 0,"stb",0,T_DD,38,0,0,0 },
  415.   { 0,"stbu",0,T_DD,39,0,0,0 },
  416.   { 0,"stbux",0,T_X,31,0,0,(247<<1) },
  417.   { 0,"stbx",0,T_X,31,0,0,(215<<1) },
  418.   { 0,"std",F_64BIT,T_DS,62,0,0,0 },
  419.   { 0,"stdcx.",F_64BIT,T_X,31,0,0,(214<<1)+1 },
  420.   { 0,"stdu",F_64BIT,T_DS,62,0,0,1 },
  421.   { 0,"stdux",F_64BIT,T_X,31,0,0,(181<<1) },
  422.   { 0,"stdx",F_64BIT,T_X,31,0,0,(149<<1) },
  423.   { 0,"stfd",0,T_DD,54,0,0,0 },
  424.   { 0,"stfdu",0,T_DD,55,0,0,0 },
  425.   { 0,"stfdux",0,T_X,31,0,0,(759<<1) },
  426.   { 0,"stfdx",0,T_X,31,0,0,(727<<1) },
  427.   { 0,"stfiwx",F_OPTIONAL,T_X,31,0,0,(983<<1) },
  428.   { 0,"stfs",0,T_DD,52,0,0,0 },
  429.   { 0,"stfsu",0,T_DD,53,0,0,0 },
  430.   { 0,"stfsux",0,T_X,31,0,0,(695<<1) },
  431.   { 0,"stfsx",0,T_X,31,0,0,(663<<1) },
  432.   { 0,"sth",0,T_DD,44,0,0,0 },
  433.   { 0,"sthbrx",0,T_X,31,0,0,(918<<1) },
  434.   { 0,"sthu",0,T_DD,45,0,0,0 },
  435.   { 0,"sthux",0,T_X,31,0,0,(439<<1) },
  436.   { 0,"sthx",0,T_X,31,0,0,(407<<1) },
  437.   { 0,"stmw",0,T_DD,47,0,0,0 },
  438.   { 0,"stswi",0,T_X,31,0,0,(725<<1) },
  439.   { 0,"stswx",0,T_X,31,0,0,(661<<1) },
  440.   { 0,"stw",0,T_DD,36,0,0,0 },
  441.   { 0,"stwbrx",0,T_X,31,0,0,(662<<1) },
  442.   { 0,"stwcx.",0,T_X,31,0,0,(150<<1)+1 },
  443.   { 0,"stwu",0,T_DD,37,0,0,0 },
  444.   { 0,"stwux",0,T_X,31,0,0,(183<<1) },
  445.   { 0,"stwx",0,T_X,31,0,0,(151<<1) },
  446.   { 0,"subf",0,T_X,31,0,0,(0<<10)+(40<<1)+0 },
  447.   { 0,"subf.",0,T_X,31,0,0,(0<<10)+(40<<1)+1 },
  448.   { 0,"subfo",0,T_X,31,0,0,(1<<10)+(40<<1)+0 },
  449.   { 0,"subfo.",0,T_X,31,0,0,(1<<10)+(40<<1)+1 },
  450.   { 0,"subfc",0,T_X,31,0,0,(0<<10)+(8<<1)+0 },
  451.   { 0,"subfc.",0,T_X,31,0,0,(0<<10)+(8<<1)+1 },
  452.   { 0,"subfco",0,T_X,31,0,0,(1<<10)+(8<<1)+0 },
  453.   { 0,"subfco.",0,T_X,31,0,0,(1<<10)+(8<<1)+1 },
  454.   { 0,"subfe",0,T_X,31,0,0,(0<<10)+(136<<1)+0 },
  455.   { 0,"subfe.",0,T_X,31,0,0,(0<<10)+(136<<1)+1 },
  456.   { 0,"subfeo",0,T_X,31,0,0,(1<<10)+(136<<1)+0 },
  457.   { 0,"subfeo.",0,T_X,31,0,0,(1<<10)+(136<<1)+1 },
  458.   { 0,"subfic",F_SIGNED,T_DI,8,0,0,0 },
  459.   { 0,"subfme",F_SUPP_B,T_X,31,0,0,(0<<10)+(232<<1)+0 },
  460.   { 0,"subfme.",F_SUPP_B,T_X,31,0,0,(0<<10)+(232<<1)+1 },
  461.   { 0,"subfmeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(232<<1)+0 },
  462.   { 0,"subfmeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(232<<1)+1 },
  463.   { 0,"subfze",F_SUPP_B,T_X,31,0,0,(0<<10)+(200<<1)+0 },
  464.   { 0,"subfze.",F_SUPP_B,T_X,31,0,0,(0<<10)+(200<<1)+1 },
  465.   { 0,"subfzeo",F_SUPP_B,T_X,31,0,0,(1<<10)+(200<<1)+0 },
  466.   { 0,"subfzeo.",F_SUPP_B,T_X,31,0,0,(1<<10)+(200<<1)+1 },
  467.   { 0,"sync",F_SUPP_D|F_SUPP_A|F_SUPP_B,T_X,31,0,0,(598<<1) },
  468.   { 0,"td",F_64BIT,T_X,31,0,0,(68<<1) },
  469.   { 0,"tdi",F_SIGNED|F_64BIT,T_DI,2,0,0,0 },
  470.   { 0,"tlbia",F_SUPP_D|F_SUPP_A|F_SUPP_B|F_SUPER|F_OPTIONAL,
  471.     T_X,31,0,0,(370<<1) },
  472.   { 0,"tlbie",F_SUPP_D|F_SUPP_A|F_SUPER|F_OPTIONAL,T_X,31,0,0,(306<<1) },
  473.   { 0,"tlbsync",F_SUPP_D|F_SUPP_A|F_SUPP_B|F_SUPER|F_OPTIONAL,
  474.     T_X,31,0,0,(566<<1) },
  475.   { 0,"tw",0,T_X,31,0,0,(4<<1) },
  476.   { 0,"twi",F_SIGNED,T_DI,3,0,0,0 },
  477.   { 0,"xor",F_SWAP,T_X,31,0,0,(316<<1)+0 },
  478.   { 0,"xor.",F_SWAP,T_X,31,0,0,(316<<1)+1 },
  479.   { 0,"xori",F_SWAP,T_DI,26,0,0,0 },
  480.   { 0,"xoris",F_SWAP,T_DI,27,0,0,0 },
  481.  
  482.   /* extended mnemonics, rest is implemented as predefined macros */
  483.   { 0,"la",F_EXTENDED,T_DD,14,0,0,0 },
  484.   { 0,0 } /* end mark */
  485. };
  486.  
  487.  
  488.  
  489. void instr(struct GlobalVars *gv,struct ParsedLine *pl)
  490. {
  491.   struct CPUInstr *ins=(struct CPUInstr *)pl->opcode;
  492.   char *op=pl->operand;
  493.   uint32 d=ins->fieldD,a=ins->fieldA;
  494.   uint32 b=0,c=0,x=0;
  495.   uint32 oc=ins->opcd<<26;
  496.   uint32 xo=ins->xo;
  497.   uint16 flags=ins->flags;
  498.   char *oldop=op;
  499.   struct Expression exp;
  500.   bool signchk=TRUE;
  501.  
  502.   if (flags & F_64BIT)
  503.     if (!gv->sixtyfourmode)
  504.       error(37,ins->name);  /* warning: 64-bit instruction */
  505.   if (flags & F_OPTIONAL)
  506.     if (!gv->optinstrmode)
  507.       error(38,ins->name);  /* warning: optional instruction */
  508.   if (flags & F_SUPER)
  509.     if (!gv->supermode)
  510.       error(39,ins->name);  /* warning: supervisor-level instruction */
  511.   gv->signedexp = flags&F_SIGNED ? TRUE:FALSE;
  512.  
  513.   switch (ins->type) {
  514.   
  515.     case T_I:  /* Bx */
  516.       op = eval_expression(gv,&exp,op);
  517.       if (exp.type < SYM_RELOC)
  518.         switch (exp.type) {
  519.           case SYM_UNDEF:
  520.             error(19);  /* undefined symbol */
  521.             break;
  522.           case SYM_ABS:
  523.             error(32);  /* Reloc symbol required */
  524.             break;
  525.         }
  526.       if (flags & F_SIGNED) {  /* relative branch */
  527.         exp.reloctype = R_PPC_REL24;
  528.         switch (exp.type) {
  529.           case SYM_RELOC:
  530.             if (exp.symbol->relsect == gv->csect)
  531.               x = exp.value - gv->csect->pc;  /* branch distance */
  532.             else {
  533.               error(33);  /* branch destination is not in current section */
  534.               x = makereloc(gv,&exp);
  535.             }
  536.             break;
  537.           case SYM_EXTERN:
  538.             x = makexref(gv,&exp,3);
  539.             break;
  540.         }
  541.         checkrange(x,3,TRUE);
  542.       }
  543.       else {  /* absolute branch */
  544.         exp.reloctype = R_PPC_ADDR24;
  545.         switch (exp.type) {
  546.           case SYM_RELOC:
  547.             x = makereloc(gv,&exp);
  548.             break;
  549.           case SYM_EXTERN:
  550.             x = makexref(gv,&exp,3);
  551.             break;
  552.         }
  553.         checkrange(x,3,FALSE);        
  554.       }
  555.       oc |= (x&0x3fffffc)|xo;
  556.       break;
  557.  
  558.     case T_B:  /* BCx */
  559.       op = getintexp(gv,op,&d);  /* BO, branch operand */
  560.       if (!(op = check_comma(op)))
  561.         break;
  562.       op = getintexp(gv,op,&a);  /* BI, branch condition index */
  563.       if (!(op = check_comma(op)))
  564.         break;
  565.       oldop = op;
  566.       op = eval_expression(gv,&exp,op);
  567.       if (exp.type < SYM_RELOC)
  568.         switch (exp.type) {
  569.           case SYM_UNDEF:
  570.             error(19);  /* undefined symbol */
  571.             break;
  572.           case SYM_ABS:
  573.             error(32);  /* Reloc symbol required */
  574.             break;
  575.         }
  576.       if (flags & F_SIGNED) {  /* relative branch */
  577.         exp.reloctype = R_PPC_REL14;
  578.         switch (exp.type) {
  579.           case SYM_RELOC:
  580.             if (exp.symbol->relsect == gv->csect) {
  581.               x = exp.value - gv->csect->pc;  /* branch distance */
  582.               if (gv->opt & OPT_FAR_BRANCH)
  583.                 opt_far_branch(gv,pl,&d,&a,(int32 *)&x,oldop);
  584.             }
  585.             else {
  586.               error(33);  /* branch destination is not in current section */
  587.               x = makereloc(gv,&exp);
  588.             }
  589.             break;
  590.           case SYM_EXTERN:
  591.             x = makexref(gv,&exp,2);
  592.             break;
  593.         }
  594.         checkrange(x,2,TRUE);
  595.       }
  596.       else {  /* absolute branch */
  597.         exp.reloctype = R_PPC_ADDR14;
  598.         switch (exp.type) {
  599.           case SYM_RELOC:
  600.             x = makereloc(gv,&exp);
  601.             break;
  602.           case SYM_EXTERN:
  603.             x = makexref(gv,&exp,2);
  604.             break;
  605.         }
  606.         checkrange(x,2,FALSE);        
  607.       }
  608.       if (flags & F_SIGNED) {
  609.         if ((int32)x >= 0)
  610.           d &= ~1;
  611.         else
  612.           d |= 1;
  613.       }
  614.       else {
  615.         if (x < gv->csect->pc && exp.symbol->relsect == gv->csect)
  616.           d |= 1;
  617.         else
  618.           d &= ~1;
  619.       }
  620.       if (pl->branch_hint > 0)  /* + */
  621.         d ^= 1;
  622.       x &= 0xfffc;
  623.       if (gv->output == OFMT_EHF) {  /* hack to allow correct EHF reloc. */
  624.         if ((flags&F_SIGNED) && (exp.type==SYM_EXTERN ||
  625.             (exp.type==SYM_RELOC && exp.symbol->relsect!=gv->csect)))
  626.           x += 2;
  627.       }
  628.       if (d>31 || a>31)
  629.         error(34);  /* Branch operand out of range */
  630.       else
  631.         oc |= (d<<21)|(a<<16)|x|xo;
  632.       break;
  633.  
  634.     case T_XLB:  /* BCLRx,BCCTRx */
  635.       op = getintexp(gv,op,&d);  /* BO, branch operand */
  636.       if (!(op = check_comma(op)))
  637.         break;
  638.       op = getintexp(gv,op,&a);  /* BI, branch condition index */
  639.       if (pl->branch_hint > 0)
  640.         d |= 1;
  641.       else if (pl->branch_hint < 0)
  642.         d &= ~1;
  643.       if (d>31 || a>31)
  644.         error(34);  /* Branch operand out of range */
  645.       else
  646.         oc |= (d<<21)|(a<<16)|xo;
  647.       break;
  648.  
  649.     case T_CMP:  /* CMP, CMPI, CMPL, CMPLI */
  650.       if (count_operands(gv,op) > 3) {  /* CR-field specified? */
  651.         op = getintexp(gv,op,&d);
  652.         if (!(op = check_comma(op)))
  653.           break;
  654.       }
  655.       op = getintexp(gv,op,&c);  /* L = word or double word */
  656.       if (!(op = check_comma(op)))
  657.         break;
  658.       op = getintexp(gv,op,&a);
  659.       if (!(op = check_comma(op)))
  660.         break;
  661.       if (flags & F_SUPP_B) {  /* immediate comparison */
  662.         op = getexp(gv,op,&x,2);
  663.         checkrange(x,2,flags&F_SIGNED);
  664.       }
  665.       else  /* register comparison */
  666.         op = getintexp(gv,op,&b);
  667.       if (d>7)
  668.         error(35);  /* CR-specifier out of range */
  669.       else if (c>1)
  670.         error(36,"L");  /* Operand field out of range */
  671.       else if (a>31 || b>31)
  672.         error(31);  /* register operand out of range */
  673.       else if (flags & F_SUPP_B)
  674.         oc |= (d<<23)|(c<<21)|(a<<16)|(x&0xffff);
  675.       else
  676.         oc |= (d<<23)|(c<<21)|(a<<16)|(b<<11)|xo;
  677.       break;
  678.  
  679.     case T_DI:  /* ADDI,ANDI,ORI */
  680.       op = getintexp(gv,op,&d);
  681.       if (!(op = check_comma(op)))
  682.         break;
  683.       op = getintexp(gv,op,&a);
  684.       if (!(op = check_comma(op)))
  685.         break;
  686.       op = getexp(gv,op,&x,2);
  687.       if (flags & F_SWAP)
  688.         swapops(&d,&a);
  689.       checkrange(x,2,flags&F_SIGNED);
  690.       if (d>31 || a>31)
  691.         error(31);  /* register operand out of range */
  692.       else
  693.         oc |= (d<<21)|(a<<16)|(x&0xffff);
  694.       break;
  695.  
  696.     case T_X:  /* ADDx, ANDx, DIVx, FMRx, .. */
  697.       if (!(flags & F_SUPP_D))
  698.         op = getintexp(gv,op,&d);
  699.       if (!(flags & F_SUPP_A)) {
  700.         if (op != oldop)
  701.           if (!(op = check_comma(op)))
  702.             break;
  703.         op = getintexp(gv,op,&a);
  704.       }
  705.       if (!(flags & F_SUPP_B)) {
  706.         if (op != oldop)
  707.           if (!(op = check_comma(op)))
  708.             break;
  709.         op = getintexp(gv,op,&b);
  710.       }
  711.       if (flags & F_CRF_D)
  712.         d <<= 2;
  713.       if (flags & F_CRF_S)
  714.         a <<= 2;
  715.       if ((d==a || d==b) && (flags & F_UPDATE))
  716.         error(58,d);  /* warning: rD = rA */
  717.       if (flags & F_SWAP)
  718.         swapops(&d,&a);
  719.       if (d>31 || a>31 || b>31)
  720.         error(31);
  721.       else
  722.         oc |= (d<<21)|(a<<16)|(b<<11)|xo;
  723.       break;
  724.  
  725.     case T_A:  /* FADDx, FSUBx, FMULx, FDIVx, .. */
  726.       if (!(flags & F_SUPP_D))
  727.         op = getintexp(gv,op,&d);
  728.       if (!(flags & F_SUPP_A)) {
  729.         if (op != oldop)
  730.           if (!(op = check_comma(op)))
  731.             break;
  732.         op = getintexp(gv,op,&a);
  733.       }
  734.       if (!(flags & F_SUPP_C)) {
  735.         if (op != oldop)
  736.           if (!(op = check_comma(op)))
  737.             break;
  738.         op = getintexp(gv,op,&c);
  739.       }
  740.       if (!(flags & F_SUPP_B)) {
  741.         if (op != oldop)
  742.           if (!(op = check_comma(op)))
  743.             break;
  744.         op = getintexp(gv,op,&b);
  745.       }
  746.       if (flags & F_SWAP) {  /* rldcl/rldcr rA,rS,rB,mb */
  747.         swapops(&d,&a);
  748.         swapops(&c,&b);
  749.       }
  750.       if (d>31 || a>31 || b>31 || c>31)
  751.         error(31);
  752.       else
  753.         oc |= (d<<21)|(a<<16)|(b<<11)|(c<<6)|xo;
  754.       break;
  755.  
  756.     case T_DD:  /* LBZ, LHA, LZWU, STBU, STW, .. */
  757.       op = getintexp(gv,op,&d);
  758.       if (!(op = check_comma(op)))
  759.         break;
  760.       if (chk_regindir(op)) {   /* rD,(rA) -> rD,0(rA) */
  761.         exp.value = 0;
  762.         exp.type = SYM_ABS;
  763.       }
  764.       else
  765.         op = eval_expression(gv,&exp,op);
  766.       if (*op++ == '(') {
  767.         op = getintexp(gv,op,&a);
  768.         if (*op++ != ')') {
  769.           error(40);  /* (rA) expected, after index expression */
  770.           op = NULL;
  771.           break;
  772.         }
  773.         if (exp.type != SYM_UNDEF) {
  774.           switch (exp.type) {
  775.             case SYM_RELOC:
  776.               if (exp.reloctype==R_PPC_ADDR16_LO ||
  777.                   exp.reloctype==R_PPC_SDAREL16) {  /* sym@l, sym@sdarx */
  778.                 x = makereloc(gv,&exp);
  779.                 signchk = FALSE;
  780.               }
  781.               else {
  782.                 if ((int)a != gv->rtoc) {  /* valid ref. to rtoc symbol? */
  783.                   /* Wrong base reg. for base rel. reloc sym. access */
  784.                   error(46);
  785.                 }
  786.                 exp.reloctype = R_PPC_SDAREL16;
  787.                 x = makereloc(gv,&exp);
  788.               }
  789.               break;
  790.             case SYM_EXTERN:  /* reference to external symbol */
  791.               if (exp.reloctype!=R_PPC_ADDR16_LO &&
  792.                   exp.reloctype!=R_PPC_SDAREL16) {
  793.                 if (gv->rtoc == (int)a)            /* ext. symbol via rtoc -  */
  794.                   exp.reloctype = R_PPC_SDAREL16;  /* might be a SDAREL16 ref.*/
  795.                 else {
  796.                   exp.reloctype = R_PPC_ADDR16;
  797.                   gv->csect->pc += 2;
  798.                   x = makexref(gv,&exp,2);
  799.                   gv->csect->pc -= 2;
  800.                   break;
  801.                 }
  802.               }
  803.               x = makexref(gv,&exp,2);
  804.               break;
  805.             default:  /* SYM_ABS */
  806.               x = exp.value;
  807.               break;
  808.           }
  809.         }
  810.         else
  811.           error(19);  /* undefined symbol */
  812.       }
  813.       else {  /* rD,v -> rD,v_off(rtoc) */
  814.         op--;
  815.         if (exp.type != SYM_UNDEF) {
  816.           switch (exp.type) {
  817.             case SYM_RELOC:
  818.               a = gv->rtoc;
  819.               exp.reloctype = R_PPC_SDAREL16;
  820.               x = makereloc(gv,&exp);
  821.               break;
  822.             case SYM_EXTERN:  /* we assume that this is a SDAREL16 reference */
  823.               a = gv->rtoc;
  824.               exp.reloctype = R_PPC_SDAREL16;
  825.               x = makexref(gv,&exp,2);
  826.               break;
  827.             default:
  828.               error(32);  /* reloc symbol required */
  829.               break;
  830.           }
  831.         }
  832.         else
  833.           error(19);
  834.       }
  835.       checkrange(x,2,signchk);
  836.       if (d == a && (flags & F_UPDATE))
  837.         error(58,d);  /* warning: rD = rA */
  838.       if (d>31 || a>31)
  839.         error(31);  /* register operand out of range */
  840.       else
  841.         oc |= (d<<21)|(a<<16)|(x&0xffff);
  842.       break;
  843.  
  844.     case T_DS:  /* LD, LDU, LWA, STD , .. */
  845.       op = getintexp(gv,op,&d);
  846.       if (!(op = check_comma(op)))
  847.         break;
  848.       if (chk_regindir(op)) {   /* rD,(rA) -> rD,0(rA) */
  849.         exp.value = 0;
  850.         exp.type = SYM_ABS;
  851.       }
  852.       else
  853.         op = eval_expression(gv,&exp,op);
  854.       if (*op++ == '(') {
  855.         op = getintexp(gv,op,&a);
  856.         if (*op++ != ')') {
  857.           error(40);  /* (rA) expected, after index expression */
  858.           op = NULL;
  859.           break;
  860.         }
  861.         if (exp.type != SYM_UNDEF) {
  862.           switch (exp.type) {
  863.             case SYM_RELOC:
  864.               if (exp.reloctype==R_PPC_ADDR16_LO ||
  865.                   exp.reloctype==R_PPC_SDAREL16) {  /* sym@l, sym@sdarx */
  866.                 x = makereloc(gv,&exp);
  867.                 signchk = FALSE;
  868.               }
  869.               else {
  870.                 if ((int)a != gv->rtoc) {  /* valid ref. to rtoc symbol? */
  871.                   /* Wrong base reg. for base rel. reloc sym. access */
  872.                   error(46);
  873.                 }
  874.                 exp.reloctype = R_PPC_SDAREL16;
  875.                 x = makereloc(gv,&exp);
  876.               }
  877.               break;
  878.             case SYM_EXTERN:  /* reference to external symbol */
  879.               if (exp.reloctype!=R_PPC_ADDR16_LO &&
  880.                   exp.reloctype!=R_PPC_SDAREL16) {
  881.                 if (gv->rtoc == (int)a)            /* ext. symbol via rtoc -  */
  882.                   exp.reloctype = R_PPC_SDAREL16;  /* might be a SDAREL16 ref.*/
  883.                 else {
  884.                   exp.reloctype = R_PPC_ADDR16;
  885.                   gv->csect->pc += 2;
  886.                   x = makexref(gv,&exp,2);
  887.                   gv->csect->pc -= 2;
  888.                   break;
  889.                 }
  890.               }
  891.               x = makexref(gv,&exp,2);
  892.               break;
  893.             default:  /* SYM_ABS */
  894.               x = exp.value;
  895.               break;
  896.           }
  897.         }
  898.         else
  899.           error(19);  /* undefined symbol */
  900.       }
  901.       else {  /* rD,v -> rD,v_off(rtoc) */
  902.         op--;
  903.         if (exp.type != SYM_UNDEF) {
  904.           switch (exp.type) {
  905.             case SYM_RELOC:
  906.               a = gv->rtoc;
  907.               exp.reloctype = R_PPC_SDAREL16;
  908.               x = makereloc(gv,&exp);
  909.               break;
  910.             case SYM_EXTERN:  /* we assume that this is a SDAREL16 reference */
  911.               a = gv->rtoc;
  912.               exp.reloctype = R_PPC_SDAREL16;
  913.               x = makexref(gv,&exp,2);
  914.               break;
  915.             default:
  916.               error(32);  /* reloc symbol required */
  917.               break;
  918.           }
  919.         }
  920.         else
  921.           error(19);
  922.       }
  923.       checkrange(x,2,signchk);
  924.       if (x & 3)
  925.         error(41);  /* expression must be dividable by four */
  926.       else if (d>31 || a>31)
  927.         error(31);  /* register operand out of range */
  928.       else
  929.         oc |= (d<<21)|(a<<16)|(x&0xfffc)|xo;
  930.       break;
  931.  
  932.     case T_XSPR:  /* MFSPR, MTSPR */
  933.       op = getintexp(gv,op,&d);
  934.       if (!(op = check_comma(op)))
  935.         break;
  936.       op = getintexp(gv,op,&a);
  937.       if (flags & F_SWAP)
  938.         swapops(&d,&a);
  939.       if (d>31 || a>0x3ff)
  940.         error(31);
  941.       else
  942.         oc |= (d<<21)|((a&0x1f)<<16)|((a&0x3e0)<<6)|xo;
  943.       break;
  944.  
  945.     case T_XCRM:  /* MFCRF */
  946.       op = getintexp(gv,op,&x);
  947.       if (!(op = check_comma(op)))
  948.         break;
  949.       op = getintexp(gv,op,&d);
  950.       if (x > 0xff)
  951.         error(42);  /* invalid register field mask */
  952.       else if (a>31)
  953.         error(31);
  954.       else
  955.         oc |= (d<<21)|(x<<12)|xo;
  956.       break;
  957.  
  958.     case T_XFL:  /* MTFSF */
  959.       op = getintexp(gv,op,&x);
  960.       if (!(op = check_comma(op)))
  961.         break;
  962.       op = getintexp(gv,op,&b);
  963.       if (x > 0xff)
  964.         error(42);  /* invalid register field mask */
  965.       else if (b>31)
  966.         error(31);
  967.       else
  968.         oc |= (x<<17)|(b<<11)|xo;
  969.       break;
  970.  
  971.     case T_IMM:  /* MTFSFI */
  972.       op = getintexp(gv,op,&d);
  973.       if (!(op = check_comma(op)))
  974.         break;
  975.       op = getintexp(gv,op,&b);
  976.       if (b>15)
  977.         error(36,"IMM");  /* operand field out of range */
  978.       else if (d>7)
  979.         error(31);
  980.       else
  981.         oc |= (d<<23)|(b<<12)|xo;
  982.       break;
  983.  
  984.     case T_MD:  /* RLDIC, .. */
  985.       op = getintexp(gv,op,&a);
  986.       if (!(op = check_comma(op)))
  987.         break;
  988.       op = getintexp(gv,op,&d);
  989.       if (!(op = check_comma(op)))
  990.         break;
  991.       op = getintexp(gv,op,&b);
  992.       if (!(op = check_comma(op)))
  993.         break;
  994.       op = getintexp(gv,op,&c);
  995.       if (b>63)
  996.         error(36,"SH");  /* operand field out of range */
  997.       else if (c>63)
  998.         error(36,"MB/ME");
  999.       else if (d>31 || a>31)
  1000.         error(31);
  1001.       else
  1002.         oc |= (d<<21)|(a<<16)|((b&0x1f)<<11)|(c<<5)|xo|((b&0x20)>>4);
  1003.       break;
  1004.  
  1005.     case T_M:  /* RLWINM, RLWNM, RLWIMI, .. */
  1006.       op = getintexp(gv,op,&a);
  1007.       if (!(op = check_comma(op)))
  1008.         break;
  1009.       op = getintexp(gv,op,&d);
  1010.       if (!(op = check_comma(op)))
  1011.         break;
  1012.       op = getintexp(gv,op,&b);
  1013.       if (!(op = check_comma(op)))
  1014.         break;
  1015.       op = getintexp(gv,op,&c);
  1016.       if (!(op = check_comma(op)))
  1017.         break;
  1018.       op = getintexp(gv,op,&x);
  1019.       if (b>31)
  1020.         error(36,"SH/rB");  /* operand field out of range */
  1021.       else if (c>31)
  1022.         error(36,"MB");
  1023.       else if (x>31)
  1024.         error(36,"ME");
  1025.       else if (d>31 || a>31)
  1026.         error(31);
  1027.       else
  1028.         oc |= (d<<21)|(a<<16)|(b<<11)|(c<<6)|(x<<1)|xo;
  1029.       break;
  1030.  
  1031.     case T_XS:  /* SRADIx */
  1032.       op = getintexp(gv,op,&a);
  1033.       if (!(op = check_comma(op)))
  1034.         break;
  1035.       op = getintexp(gv,op,&d);
  1036.       if (!(op = check_comma(op)))
  1037.         break;
  1038.       op = getintexp(gv,op,&b);
  1039.       if (b>63)
  1040.         error(36,"SH");  /* operand field out of range */
  1041.       else if (d>31 || a>31)
  1042.         error(31);
  1043.       else
  1044.         oc |= (d<<21)|(a<<16)|((b&0x1f)<<11)|xo|((b&0x20)>>4);
  1045.       break;
  1046.   }
  1047.  
  1048.   store_word(gv,oc);
  1049.   if (op)
  1050.     checkEOL(op);
  1051. }
  1052.  
  1053.  
  1054. static void opt_far_branch(struct GlobalVars *gv,struct ParsedLine *pl,
  1055.                            uint32 *bo,uint32 *bi,int32 *bd,char *lab)
  1056. /* If branch destination is out of range, convert into a */
  1057. /* B!cc $+8 / B combination. */
  1058. {
  1059.   if (*bd>0x7fff || *bd<-0x8000) {
  1060.     struct ParsedLine *newpl = alloczero(sizeof(struct ParsedLine));
  1061.     char buf[STRBUFSIZE];
  1062.  
  1063.     move_symbols(gv,(uint32)gv->csect->pc,4); /* space for new instruction */
  1064.     *bo ^= 8;  /* negate condition */
  1065.     *bd = 8;   /* branch displacement = "$+8" */
  1066.     newpl->type = OT_INSTRUCTION;
  1067.     newpl->flags = pl->flags;
  1068.     newpl->narg = pl->narg;
  1069.     newpl->lineptr = pl->lineptr;
  1070.     newpl->opcode = (void *)search_instr(gv,"b");
  1071.     newpl->operand = lab;
  1072.     newpl->next = pl->next;
  1073.     /* free(pl->operand); @@@@ ? */
  1074.     sprintf(buf,"%d,%d,$+8",(int)*bo,(int)*bi);
  1075.     pl->branch_hint = -(pl->branch_hint);
  1076.     pl->operand = allocstring(buf);
  1077.     pl->next = newpl;
  1078.   }
  1079. }
  1080.  
  1081.  
  1082. static void swapops(uint32 *a,uint32 *b)
  1083. {
  1084.   uint32 c = *a;
  1085.  
  1086.   *a = *b;
  1087.   *b = c;
  1088. }
  1089.  
  1090.  
  1091. static int count_operands(struct GlobalVars *gv,char *s)
  1092. {
  1093.   int n=0;
  1094.  
  1095.   if (*s!=0 && *s!='#')
  1096.     do {
  1097.       n++;
  1098.       s = skipexpression(gv,s);
  1099.     }
  1100.     while (*s++ == ',');
  1101.   return (n);
  1102. }
  1103.  
  1104.  
  1105. static bool chk_regindir(char *s)
  1106. /* "(...)\0" has a high probability to be a register-indirect */
  1107. /* addressing mode. */
  1108. {
  1109.   char c;
  1110.  
  1111.   if (*s++ == '(') {
  1112.     while (c = *s++) {
  1113.       if (c == '(')
  1114.         break;           /* "((..." will never be register-indirect */
  1115.       if (c == ')') {
  1116.         s = skipspaces(s);
  1117.         if (*s == '\0')  /* line ends directly after "(...)" ? */
  1118.           return (TRUE);
  1119.         else
  1120.           break;
  1121.       }
  1122.     }
  1123.   }
  1124.   return (FALSE);
  1125. }
  1126.  
  1127.  
  1128. static void move_symbols(struct GlobalVars *gv,uint32 so,int32 d)
  1129. /* All relocatable symbols of current section with a greater */
  1130. /* section-offset than 'so' are moved by delta 'd'. */
  1131. {
  1132.   struct AlignPoint *ap = gv->csect->current_align;
  1133.   long g,a;
  1134.   unsigned long off;
  1135.  
  1136.   move_aligned_symbols_offset(gv,ap,so,d);
  1137.   while (ap = ap->next) {
  1138.     g = ap->gap - d;
  1139.     a = ap->val;
  1140.     off = ap->offset + ap->gap;  /* current offset after alignment */
  1141.     ap->offset += d;             /* new align-point offset */
  1142.     if (g<0 || g>=a) {  /* need to move the alignment point? */
  1143.       g = (a - (ap->offset & (a-1))) & (a-1);
  1144.       d = ap->offset + g - off;
  1145.       ap->gap = g;
  1146.       move_aligned_symbols_all(gv,ap,d);    
  1147.     }
  1148.     else {  /* delta is neutralized by alignment gap */
  1149.       ap->gap = g;
  1150.       break;
  1151.     }
  1152.   }
  1153.   gv->csect->data = NULL;  /* no further data is written to section */
  1154.   gv->anotherpass = TRUE;  /* this requires another pass :( */
  1155. }
  1156.  
  1157.  
  1158. static void move_aligned_symbols_offset(struct GlobalVars *gv,
  1159.                                         struct AlignPoint *ap,
  1160.                                         uint32 so,int32 d)
  1161. {
  1162.   struct Symbol *sym;
  1163.   struct Symbol **symtab = gv->symbols;
  1164.   int i;
  1165.  
  1166.   for (i=0; i<SYMHTABSIZE; i++) {
  1167.     sym = *symtab++;
  1168.     while (sym) {
  1169.       if (sym->type == SYM_RELOC)
  1170.         if (sym->alignpoint == ap)
  1171.           if (sym->value > so)
  1172.             sym->value += d;
  1173.       sym = sym->hash_chain;
  1174.     }
  1175.   }
  1176. }
  1177.  
  1178.  
  1179. static void move_aligned_symbols_all(struct GlobalVars *gv,
  1180.                                      struct AlignPoint *ap,int32 d)
  1181. {
  1182.   struct Symbol *sym;
  1183.   struct Symbol **symtab = gv->symbols;
  1184.   int i;
  1185.  
  1186.   for (i=0; i<SYMHTABSIZE; i++) {
  1187.     sym = *symtab++;
  1188.     while (sym) {
  1189.       if (sym->type==SYM_RELOC && sym->alignpoint==ap)
  1190.         sym->value += d;
  1191.       sym = sym->hash_chain;
  1192.     }
  1193.   }
  1194. }
  1195.  
  1196.  
  1197. char *check_comma(char *s)
  1198. {
  1199.   s = skipspaces(s);
  1200.   if (*s++ != ',') {
  1201.     error(27);  /* instruction has too few operands */
  1202.     return (NULL);
  1203.   }
  1204.   s = skipspaces(s);
  1205.   return (s);
  1206. }
  1207.  
  1208.  
  1209. void pcadd(struct GlobalVars *gv,unsigned long offset)
  1210. {
  1211.   gv->csect->pc += offset;
  1212. }
  1213.  
  1214.  
  1215. void store_byte(struct GlobalVars *gv,uint8 x)
  1216. {
  1217.   struct Section *sec = gv->csect;
  1218.   uint8 *d;
  1219.  
  1220.   if (d = (uint8 *)sec->data) {
  1221.     *d++ = x;
  1222.     sec->data = d;
  1223.   }
  1224.   sec->pc += 1;
  1225.   gv->lcsym->value += 1;
  1226. }
  1227.  
  1228.  
  1229. void store_half(struct GlobalVars *gv,uint16 x)
  1230. {
  1231.   struct Section *sec = gv->csect;
  1232.   uint16 *d;
  1233.  
  1234.   if (d = (uint16 *)sec->data) {
  1235.     *d++ = ECVH(x);
  1236.     sec->data = d;
  1237.   }
  1238.   sec->pc += 2;
  1239.   gv->lcsym->value += 2;
  1240. }
  1241.  
  1242.  
  1243. void store_word(struct GlobalVars *gv,uint32 x)
  1244. {
  1245.   struct Section *sec = gv->csect;
  1246.   uint32 *d;
  1247.  
  1248.   if (d = (uint32 *)sec->data) {
  1249.     *d++ = ECVW(x);
  1250.     sec->data = d;
  1251.   }
  1252.   sec->pc += 4;
  1253.   gv->lcsym->value += 4;
  1254. }
  1255.  
  1256.  
  1257. void store_float(struct GlobalVars *gv,double x)
  1258. {
  1259.   struct Section *sec = gv->csect;
  1260.   float *d;
  1261.  
  1262.   if (d = (float *)sec->data) {
  1263.     *d++ = (float)x;
  1264.     sec->data = d;
  1265.   }
  1266.   sec->pc += 4;
  1267.   gv->lcsym->value += 4;
  1268. }
  1269.  
  1270.  
  1271. void store_double(struct GlobalVars *gv,double x)
  1272. {
  1273.   struct Section *sec = gv->csect;
  1274.   double *d;
  1275.  
  1276.   if (d = (double *)sec->data) {
  1277.     *d++ = x;
  1278.     sec->data = d;
  1279.   }
  1280.   sec->pc += 8;
  1281.   gv->lcsym->value += 8;
  1282. }
  1283.  
  1284.  
  1285. void store_space(struct GlobalVars *gv,unsigned long n)
  1286. {
  1287.   struct Section *sec = gv->csect;
  1288.   uint8 *d;
  1289.  
  1290.   sec->pc += n;
  1291.   gv->lcsym->value += n;
  1292.   if (d = (uint8 *)sec->data) {
  1293.     while (n--)
  1294.       *d++ = 0;
  1295.     sec->data = d;
  1296.   }
  1297. }
  1298.